import ctypes
import hashlib
import inspect
import os
import shutil
import sqlite3
import time
from datetime import datetime, timedelta
from ftplib import FTP
from threading import Thread

# 获取当前路径下所有文件名
from log import Log


def get_files(file_path):
    return os.listdir(file_path)


# 获取本地文件最后一次修改时间，越大说明文件越新
def get_local_last_modify(p):
    return datetime.utcfromtimestamp(os.stat(p).st_mtime) + timedelta(hours=8)


def get_date(d):
    tokens = d.split('-')
    return '20' + tokens[2] + '-' + tokens[0] + '-' + tokens[1]


def get_time(t):
    hour = int(t[0:2])
    minute = t[3:5]
    m = t[5:7]
    if m == 'PM':
        if hour != 12:
            hour = hour + 12
    if m == 'AM':
        if hour == 12:
            hour = hour - 12
    hour = str(hour)
    return hour + ':' + minute + ':00'


# 获取本地文件md5码
def get_md5(f):
    with open(f, 'rb') as file:
        return hashlib.md5(file.read()).hexdigest()


def _async_raise(tid, exc_type):
    tid = ctypes.c_long(tid)
    if not inspect.isclass(exc_type):
        exc_type = type(exc_type)
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exc_type))
    if res == 0:
        raise ValueError("invalid thread id")
    elif res != 1:
        ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
        raise SystemError("PyThreadState_SetAsyncExc failed")


def stop_thread(thread):
    _async_raise(thread.ident, SystemExit)


# 获取文件本身名字（不加路径）
def get_ftp_file_real_name(file_name):
    return str(file_name).split('/')[-1]


# 获取当前时间
def get_now_time():
    now = time.localtime()
    now_time = time.strftime("%Y-%m-%d %H:%M:%S", now)
    return now_time


# 自定义ftp连接类
class FtpConnect:
    host = ''
    port = 21
    username = ''
    password = ''
    ftpDirs = []  # 存放ftp目录
    ftp = None
    md5 = ''
    mode = 1  # 同步模式:0双向 1本地为主 2服务端为主
    ignore = []  # 忽略列表
    running = True
    thread = None
    interval = 10  # 默认间隔
    Dirs = {}  # 存放ftp目录与本地目录的字典
    cwd = ''  # 当前工作目录
    current_files = []  # 正在同步的目录

    def __init__(self, host='', port=21, username='', password=''):
        self.port = port
        self.password = password
        self.username = username
        self.host = host
        self.ftp = FTP(encoding='gbk')
        self.md5 = 'md5.txt'
        self.mode = 1
        self.cwd = os.getcwd()
        if host:
            self.ftp.connect(host, port)
            if username:
                self.login(username, password)

    # 登录
    def login(self, username, password):
        self.ftp.login(username, password)
        self.ftpDirs = self.ftp.nlst()
        conn = sqlite3.connect('ignore.db')
        cursor = conn.cursor()
        cursor.execute('create table if not exists dir(ftpdir varchar(255), localdir varchar(255))')
        cursor.execute('select * from dir')
        data = cursor.fetchall()
        cursor.close()
        conn.close()
        for i in data:
            self.Dirs[i[0]] = i[1]
        self.get_ignore()
        if not os.path.exists(self.md5):
            with open(self.md5, 'w'):
                pass

    # 删除ftp文件与本地文件的映射
    def del_dirs(self, file):
        conn = sqlite3.connect('ignore.db')
        cursor = conn.cursor()
        cursor.execute('delete from dir where ftpdir = ?', [file])
        if file in self.Dirs.keys():
            self.Dirs.pop(file)
        cursor.close()
        conn.commit()
        conn.close()

    # 更改ftp文件与本地文件的映射 如果不存在就增加 有就修改
    def update_dirs(self, local_dir, ftp_dir):
        conn = sqlite3.connect('ignore.db')
        cursor = conn.cursor()
        if ftp_dir not in self.Dirs.keys():
            cursor.execute('insert into dir(ftpdir, localdir) values(?,?)', [ftp_dir, local_dir])
        else:
            cursor.execute('update dir set localdir = ? where ftpdir = ?', [local_dir, ftp_dir])
        self.Dirs[ftp_dir] = local_dir
        cursor.close()
        conn.commit()
        conn.close()
        return True

    # 获取文件夹同步状态
    def get_status(self, local_path, remote_path):
        try:
            self.ftp.cwd(remote_path)  # 进入FTP工作目录
        except Exception:
            return False
        if self.mode == 1:
            try:
                file_list = os.listdir(local_path)
                for file_name in file_list:
                    rf = self.get_file_name(file_name)
                    if rf in self.ignore:
                        pass
                    elif os.path.isdir(os.path.join(local_path, file_name)):
                        try:
                            cwd = self.ftp.pwd()
                            self.ftp.cwd(file_name)
                            self.ftp.cwd(cwd)
                        except Exception:
                            self.ftp.cwd("..")
                            return False
                        p_local_path = os.path.join(local_path, file_name)  # 拼接本地第一层子目录，递归时进入下一层
                        p_remote_path = self.ftp.pwd() + '/' + file_name  # 拼接FTP第一层子目录，递归时进入下一层
                        status = self.get_status(p_local_path, p_remote_path)  # 递归
                        if not status:
                            self.ftp.cwd("..")
                            return False
                    else:
                        p_local_file = os.path.join(local_path, file_name)
                        try:
                            if get_md5(p_local_file) != self.get_ftp_md5(file_name):
                                self.ftp.cwd("..")
                                return False
                        except Exception:
                            self.ftp.cwd("..")
                            return False
            except Exception as e:
                print(e)
                return False
        else:
            try:
                file_list = self.ftp.nlst()
                for file_name in file_list:
                    rf = self.get_file_name(file_name)
                    if rf in self.ignore:
                        pass
                    elif len(self.ftp.nlst(file_name)) == 0:  # 空目录
                        p_local_path = os.path.join(local_path, file_name)
                        if not os.path.exists(p_local_path):
                            self.ftp.cwd("..")
                            return False
                    elif get_ftp_file_real_name(file_name) == get_ftp_file_real_name(self.ftp.nlst(file_name)[0]):
                        p_local_file = os.path.join(local_path, file_name)
                        try:
                            if get_md5(p_local_file) != self.get_ftp_md5(file_name):
                                self.ftp.cwd("..")
                                return False
                        except Exception:
                            self.ftp.cwd("..")
                            return False
                    else:
                        p_local_path = os.path.join(local_path, file_name)
                        if not os.path.exists(p_local_path):
                            self.ftp.cwd("..")
                            return False
                        p_remote_path = self.ftp.pwd() + '/' + file_name  # 拼接FTP第一层子目录，递归时进入下一层
                        status = self.get_status(p_local_path, p_remote_path)  # 递归
                        if not status:
                            self.ftp.cwd("..")
                            return False
            except Exception as e:
                print(e)
        self.ftp.cwd("..")
        return True

    # 获取文件夹大小
    def get_size(self, path):
        self.ftp.cwd(path)  # 进入FTP工作目录
        size = 0
        file_list = self.ftp.nlst()
        for file_name in file_list:
            if len(self.ftp.nlst(file_name)) == 0:  # 空目录
                pass
            elif get_ftp_file_real_name(file_name) == get_ftp_file_real_name(self.ftp.nlst(file_name)[0]):  # 文件
                size = size + self.ftp.size(file_name)
            else:  # 非空目录 递归进入
                p_path = self.ftp.pwd() + '/' + file_name
                size = size + self.get_size(p_path)  # 递归
        self.ftp.cwd('..')
        return size

    # 设置扫描时间
    def set_interval(self, interval):
        self.interval = interval
        print('interval:' + str(interval))

    # 设置同步模式
    def set_mode(self, mode):
        self.mode = mode
        print('mode:' + str(mode))

    # 删除ftp文件或目录
    def delete_path(self, path):
        self.ftp.cwd(path)
        dirlist = self.ftp.nlst()
        for f in dirlist:
            if len(self.ftp.nlst(f)) == 0:  # 空目录
                self.ftp.rmd(f)
            elif f == self.ftp.nlst(f)[0]:  # 文件
                self.ftp.delete(f)
            else:  # 目录
                file_path = self.ftp.pwd() + '/' + f
                self.delete_path(file_path)
        self.ftp.cwd('..')
        self.ftp.rmd(path)
        self.del_ignore(path)
        log = Log(path, 1, get_now_time(), self.ftp.pwd() + '/' + path, -1)
        self.print_log(log)

    # 创建本地目录
    def add_local_dir(self, file):
        os.makedirs(file)
        log = Log(str(file).split('\\')[-1], 0, get_now_time(), file, -1)
        self.print_log(log)

    # 获取ftp目录下文件
    def get_ftp_files(self, file_name):
        if len(self.ftp.nlst(file_name)) == 0:
            return []
        elif get_ftp_file_real_name(file_name) == get_ftp_file_real_name(self.ftp.nlst(file_name)[0]):
            return False
        else:
            files = []
            for f in self.ftp.nlst(file_name):
                if file_name == '':
                    temp = '/' + get_ftp_file_real_name(f)
                    if temp not in self.ignore:
                        files.append(f)
                else:
                    temp = '/' + file_name + '/' + get_ftp_file_real_name(f)
                    if temp not in self.ignore:
                        files.append(f)
            return files

    # 启动同步 以开启一个线程的方式
    def start(self):
        if self.thread is not None:
            stop_thread(self.thread)
        self.thread = Thread(target=self.run)
        self.thread.start()

    # 停止或继续
    def stop(self):
        if not self.running:
            self.running = True
        else:
            self.running = False

    # 获取本地文件在ftp中对应的文件
    def get_cwd(self, file):
        cwd = self.cwd
        if file in self.Dirs.keys():
            cwd = self.Dirs[file]
        return cwd

    def initial(self):
        if self.mode == 1:  # 本地为主
            for file in os.listdir(self.cwd):  # 默认工作空间扫描
                local_path = self.get_local_path(file)
                if file in self.ignore:
                    pass
                elif os.path.isdir(local_path):  # 是一个目录
                    if file not in self.ftpDirs:  # 但ftp不存在时
                        self.ftp.mkd(file)
                        self.ftpDirs.append(file)
                        self.ini(local_path, file)
                    else:  # ftp存在
                        pass
                else:  # 不是目录，跳过
                    pass
            for file in self.Dirs.keys():  # 其他工作空间
                local_path = self.get_local_path(file)
                if file in self.ignore:
                    pass
                elif not os.path.exists(local_path):  # 本地不存在
                    self.del_dirs(file)
                    if file in self.ftpDirs:  # 但ftp存在
                        self.delete_path(file)
                        self.ftpDirs.remove(file)
                    else:
                        pass
                elif os.path.exists(local_path):  # 本地存在
                    if file not in self.ftpDirs:  # 但ftp不存在
                        self.ftp.mkd(file)
                        self.ftpDirs.append(file)
                        self.ini(local_path, file)
                    else:
                        pass
            for file in self.ftpDirs:  # 删除ftp服务器中，本地没有的目录
                if file in self.ignore:
                    pass
                elif file not in os.listdir(self.cwd) and file not in self.Dirs.keys():  # 默认空间和其他空间都不包含
                    self.delete_path(file)
                    self.ftpDirs.remove(file)
                else:
                    pass
        elif self.mode == 0:  # 双向同步
            for file in self.ftpDirs:  # 扫描ftp中的目录
                local_path = self.get_local_path(file)
                if file in self.ignore:
                    pass
                elif file not in self.Dirs.keys():  # 不在本地其他工作空间
                    if file not in os.listdir(self.cwd):  # 并且也不在本地默认空间
                        os.mkdir(local_path)
                        self.ini(local_path, file)
                    else:  # 在本地默认空间
                        pass
                else:  # 在本地其他工作空间
                    if not os.path.exists(local_path):  # 但在本地没有该目录
                        os.mkdir(local_path)
                        self.ini(local_path, file)
                    else:  # 并且存在该目录
                        pass
        elif self.mode == 2:
            for file in self.ftpDirs:  # 扫描ftp目录
                local_path = self.get_local_path(file)
                if file in self.ignore:
                    pass
                elif file not in os.listdir(self.cwd):  # 不在本地默认空间
                    if file in self.Dirs.keys():  # 在本地其它空间
                        if not os.path.exists(local_path):  # 本地不存在
                            os.mkdir(local_path)
                            self.ini(local_path, file)
                        else:  # 本地存在
                            pass
                    else:  # 都不存在
                        os.mkdir(local_path)
                        self.ini(local_path, file)
                else:  # 在本地默认空间
                    pass
            for file in os.listdir(self.cwd):  # 扫描本地默认空间，有ftp不存在的目录就删除
                local_path = self.get_local_path(file)
                if file in self.ignore:
                    pass
                elif file not in self.ftpDirs:  # ftp中不存在
                    if os.path.isdir(local_path):  # 是目录就删除
                        shutil.rmtree(local_path)
                    else:
                        pass
                else:
                    pass
            for file in self.Dirs.keys():  # 扫描本地其他工作空间
                local_path = self.get_local_path(file)
                if file in self.ignore:
                    pass
                elif file not in self.ftpDirs:  # ftp中不存在
                    self.del_dirs(file)
                    if os.path.exists(local_path):
                        shutil.rmtree(local_path)
                else:  # ftp中存在
                    pass
        print('初始化完成...')

    # 添加正在同步的目录
    def add_current(self, file):
        if file in self.ftpDirs and file not in self.current_files:
            self.current_files.append(file)
            return True
        else:
            return False

    # 去掉正在同步的目录
    def remove_current(self, file):
        if file in self.ftpDirs and file in self.current_files:
            self.current_files.remove(file)
            return True
        else:
            return False

    # 同步
    def run(self):
        while self.running:
            for ftpDir in self.ftpDirs:  # 开始同步
                if ftpDir in self.current_files:
                    local_path = self.get_local_path(ftpDir)
                    if ftpDir not in self.ignore:  # 忽略列表
                        if self.mode == 0:
                            print(f'{ftpDir}:双向同步')
                            self.download_file_tree(local_path, ftpDir)
                            self.upload_file_tree(local_path, ftpDir)
                        elif self.mode == 1:
                            print(f'{ftpDir}:本地主同步')
                            self.upload_file_tree(local_path, ftpDir)
                        elif self.mode == 2:
                            print(f'{ftpDir}:ftp主同步')
                            self.download_file_tree(local_path, ftpDir)
            time.sleep(self.interval)
        print('已退出')

    # 获取与ftp目录对应的本地目录
    def get_local_files(self):
        local_files = []
        for ftp_file in self.ftpDirs:
            local_files.append(self.get_local_path(ftp_file))
        return local_files

    # 获取与ftp目录对应的本地文件路径
    def get_local_path(self, file):
        local_path = os.path.join(self.cwd, file)
        if file in self.Dirs.keys():
            local_path = self.Dirs[file]
        return local_path

    # 获取忽略列表
    def get_ignore(self):
        conn = sqlite3.connect('ignore.db')
        cursor = conn.cursor()
        # cursor.execute('drop table ignore')
        cursor.execute('create table if not exists ignore(file_name varchar(255))')
        cursor.execute('select * from ignore')
        datas = cursor.fetchall()
        self.ignore.clear()
        for i in datas:
            self.ignore.append(i[0])
        cursor.close()
        conn.commit()
        conn.close()

    # 删除忽略
    def del_ignore(self, file_name):
        if file_name in self.ignore:
            self.ignore.remove(file_name)
            conn = sqlite3.connect('ignore.db')
            cursor = conn.cursor()
            cursor.execute('delete from ignore where file_name = ?', [file_name])
            cursor.close()
            conn.commit()
            conn.close()

    # 添加忽略
    def add_ignore(self, file_name):
        if file_name not in self.ignore:
            conn = sqlite3.connect('ignore.db')
            cursor = conn.cursor()
            cursor.execute('insert into ignore(file_name) values(?)', [file_name])
            self.ignore.append(file_name)
            cursor.close()
            conn.commit()
            conn.close()

    # 添加ftp目录
    def add_ftp(self, ftp_dir):
        try:
            self.ftp.mkd(ftp_dir)
            print('创建成功')
            self.ftpDirs.append(ftp_dir)
            log = Log(ftp_dir, 1, get_now_time(), self.ftp.pwd() + '/' + ftp_dir, 1)
            self.print_log(log)
            return True
        except Exception as e:
            print('已存在该目录', e)
            return False

    # 删除ftp目录
    def del_ftp(self, ftp_dir):
        try:
            self.delete_path(ftp_dir)
            print('删除成功')
            self.ftpDirs.remove(ftp_dir)
            self.del_dirs(ftp_dir)
            self.del_ignore(ftp_dir)
            return True
        except Exception as e:
            print('不存在该目录', e)
            return False

    # 获取文件/目录最后一次修改时间 flag:true文件 false目录
    def get_ftp_last_modify(self, p, flag):
        names = p.split('/')
        name = names[-1]
        if not flag:  # 目录
            self.ftp.cwd('..')
            data = []
            self.ftp.dir(data.append)
            self.ftp.cwd(p)
            for i in data:
                token = i.split(maxsplit=3)
                if token[3] == name.strip('/'):
                    d = get_date(token[0])
                    t = get_time(token[1])
                    ds = d.split('-')
                    ts = t.split(':')
                    return datetime(int(ds[0]), int(ds[1]), int(ds[2]), int(ts[0]), int(ts[1]), int(ts[2]))
        else:
            x = list(self.ftp.sendcmd('MDTM ' + p))
            dir_t = x[4] + x[5] + x[6] + x[7] + '-' + x[8] + x[9] + '-' + x[10] + x[11] + ' ' + x[12] + x[13] + ':' + x[
                14] + x[15] + ':' + x[16] + x[17]
            return datetime.fromisoformat(dir_t) + timedelta(hours=8)

    # 获取ftp文件的md5码
    def get_ftp_md5(self, f):
        with open(self.md5, 'wb') as file:
            self.ftp.retrbinary('RETR ' + f, file.write)
        with open(self.md5, 'rb') as file:
            data = file.read()
            return hashlib.md5(data).hexdigest()

    # 上传文件
    def upload_file(self, local_file, remote_file):
        rf = self.get_file_name(remote_file)
        if rf in self.ignore:
            pass
        else:
            try:
                with open(local_file, 'rb') as f:
                    self.ftp.storbinary('STOR ' + remote_file, f)
            except Exception as err:
                print(f'上传文件有错误发生:{local_file}, 错误:{err}')

    # 下载文件
    def download_file(self, local_file, remote_file):
        rf = self.get_file_name(remote_file)
        if rf in self.ignore:
            pass
        else:
            try:
                with open(local_file, 'wb') as f:
                    self.ftp.retrbinary('RETR ' + remote_file, f.write)
            except Exception as err:
                print(f'下载文件有错误发生:{remote_file}, 错误:{err}')

    # 上传文件夹
    def upload_file_tree(self, local_path, remote_path):
        try:
            self.ftp.cwd(remote_path)  # 进入FTP工作目录
        except Exception as e:
            print(f'FTP目录：{remote_path}目录不存在', e)
            base_dir, part_path = self.ftp.pwd(), remote_path.split('/')
            for sub_path in part_path:
                if '' == sub_path:  # 如果是空字符，跳出此循环，执行下一个。
                    continue
                base_dir = os.path.join(base_dir, sub_path)  # base_dir + sub_path  # 拼接子目录
                try:
                    self.ftp.cwd(base_dir)  # 进入目录
                except Exception:
                    log = Log(sub_path, 1, get_now_time(), base_dir, 1)
                    self.print_log(log)
                    self.ftp.mkd(base_dir)  # 不存在创建当前子目录 直到创建所有
                    continue
            self.ftp.cwd(remote_path)  # 进入FTP工作目录
        try:
            # 远端目录通过ftp对象已经切换到指定目录或创建的指定目录
            file_list = os.listdir(local_path)  # 列出本地文件夹第一层目录的所有文件和目录
            for file_name in file_list:
                rf = self.get_file_name(file_name)
                if rf in self.ignore:
                    pass
                elif os.path.isdir(os.path.join(local_path, file_name)):  # 判断是文件还是目录，是目录为真
                    # 使用FTP进入远程目录，如果没有远程目录则创建它
                    try:  # 如果是目录，则尝试进入到这个目录，再退出来。
                        cwd = self.ftp.pwd()  # 获取FTP当前路径
                        self.ftp.cwd(file_name)  # 如果cwd成功 则表示该目录存在 退出到上一级
                        self.ftp.cwd(cwd)  # 再返回FTP之前的目录
                    except Exception:
                        self.ftp.mkd(file_name)  # 建立目录
                        log = Log(file_name, 1, get_now_time(), self.ftp.pwd() + '/' + file_name, 1)
                        self.print_log(log)
                    p_local_path = os.path.join(local_path, file_name)  # 拼接本地第一层子目录，递归时进入下一层
                    p_remote_path = self.ftp.pwd() + '/' + file_name  # 拼接FTP第一层子目录，递归时进入下一层
                    self.upload_file_tree(p_local_path, p_remote_path)  # 递归
                else:
                    # 是文件
                    p_local_file = os.path.join(local_path, file_name)
                    try:
                        if get_md5(p_local_file) != self.get_ftp_md5(file_name):
                            if get_local_last_modify(p_local_file) > self.get_ftp_last_modify(file_name, True):
                                self.upload_file(p_local_file, file_name)
                                log = Log(file_name, 1, get_now_time(), self.ftp.pwd() + '/' + file_name, 0)
                                self.print_log(log)
                            else:
                                self.download_file(p_local_file, file_name)
                                log = Log(file_name, 0, get_now_time(), p_local_file, 0)
                                self.print_log(log)
                    except Exception:
                        if get_local_last_modify(local_path) > self.get_ftp_last_modify(remote_path,
                                                                                        False):  # 上传文件
                            self.upload_file(p_local_file, file_name)
                            log = Log(file_name, 1, get_now_time(), self.ftp.pwd() + '/' + file_name, 1)
                            self.print_log(log)
                        else:  # 删除本地文件
                            os.remove(p_local_file)
                            log = Log(file_name, 0, get_now_time(), p_local_file, -1)
                            self.print_log(log)
        except Exception as e:
            print(f'上传文件出错', e)
        self.ftp.cwd("..")  # 对于递归 ftp 每次传输完成后需要切换目录到上一级

    # 获取ftp上的文件名
    def get_file_name(self, file_path):
        file = file_path.split('\\')[-1]
        return self.ftp.pwd() + '/' + file

    # 初始化
    def ini(self, local_path, remote_path):
        self.ftp.cwd(remote_path)  # 进入FTP工作目录
        if self.mode == 2:  # ftp主同步
            try:
                file_list = self.ftp.nlst()
                for file_name in file_list:
                    rf = self.get_file_name(file_name)
                    if rf in self.ignore:
                        pass
                    elif len(self.ftp.nlst(file_name)) == 0:  # 空目录
                        p_local_path = os.path.join(local_path, file_name)
                        if not os.path.exists(p_local_path):
                            print(f'本地目录{p_local_path}不存在，正在创建')
                            os.mkdir(p_local_path)
                            print('创建成功')
                    elif get_ftp_file_real_name(file_name) == get_ftp_file_real_name(self.ftp.nlst(file_name)[0]):  # 文件
                        p_local_file = os.path.join(local_path, file_name)
                        self.download_file(p_local_file, file_name)
                    else:  # 非空目录 递归进入
                        p_local_path = os.path.join(local_path, file_name)
                        if not os.path.exists(p_local_path):
                            print(f'目录{p_local_path}不存在，正在创建')
                            os.mkdir(p_local_path)
                            print('创建成功')
                        p_remote_path = self.ftp.pwd() + '/' + file_name  # 拼接FTP第一层子目录，递归时进入下一层
                        self.ini(p_local_path, p_remote_path)  # 递归
                local_list = os.listdir(local_path)
                for file in local_list:
                    if file not in file_list:
                        if os.path.isdir(file):
                            shutil.rmtree(file)
                        else:
                            os.remove(file)
            except Exception as e:
                print(f'下载文件出错{e}')
        elif self.mode == 1:  # 本地主同步
            file = os.listdir(local_path)
            for f in file:
                real_url = os.path.join(local_path, f)
                p_remote_path = self.ftp.pwd() + '/' + f
                rf = self.get_file_name(f)
                if rf in self.ignore:
                    pass
                elif os.path.isfile(real_url):  # 文件
                    self.upload_file(real_url, f)
                elif os.path.isdir(real_url):  # 目录
                    if os.listdir(real_url):  # 非空目录
                        if f not in self.ftp.nlst():
                            print(f'ftp目录{p_remote_path}不存在，正在创建')
                            self.ftp.mkd(f)
                            print('创建成功')
                            self.ini(real_url, p_remote_path)
                    else:  # 空目录
                        print(f'ftp目录{p_remote_path}不存在，正在创建')
                        self.ftp.mkd(f)
                        print('创建成功')
        elif self.mode == 0:
            try:
                file_list = self.ftp.nlst()
                for file_name in file_list:
                    rf = self.get_file_name(file_name)
                    if rf in self.ignore:
                        pass
                    elif len(self.ftp.nlst(file_name)) == 0:  # 空目录
                        p_local_path = os.path.join(local_path, file_name)
                        if not os.path.exists(p_local_path):
                            print(f'本地目录{p_local_path}不存在，正在创建')
                            os.mkdir(p_local_path)
                            print('创建成功')
                    elif get_ftp_file_real_name(file_name) == get_ftp_file_real_name(self.ftp.nlst(file_name)[0]):  # 文件
                        p_local_file = os.path.join(local_path, file_name)
                        self.download_file(p_local_file, file_name)
                    else:  # 非空目录 递归进入
                        p_local_path = os.path.join(local_path, file_name)
                        if not os.path.exists(p_local_path):
                            print(f'目录{p_local_path}不存在，正在创建')
                            os.mkdir(p_local_path)
                            print('创建成功')
                        p_remote_path = self.ftp.pwd() + '/' + file_name  # 拼接FTP第一层子目录，递归时进入下一层
                        self.ini(p_local_path, p_remote_path)  # 递归
            except Exception as e:
                print(e)
        self.ftp.cwd('..')  # 对于递归 ftp 每次传输完成后需要切换目录到上一级

    # 下载文件夹
    def download_file_tree(self, local_path, remote_path):
        self.ftp.cwd(remote_path)  # 进入FTP工作目录
        try:
            file_list = self.ftp.nlst()
            for file_name in file_list:
                rf = self.get_file_name(file_name)
                if rf in self.ignore:
                    pass
                elif len(self.ftp.nlst(file_name)) == 0:  # 空目录
                    p_local_path = os.path.join(local_path, file_name)
                    if not os.path.exists(p_local_path):
                        os.mkdir(p_local_path)
                        log = Log(file_name, 0, get_now_time(), p_local_path, 1)
                        self.print_log(log)
                elif get_ftp_file_real_name(file_name) == get_ftp_file_real_name(self.ftp.nlst(file_name)[0]):  # 如果是文件
                    p_local_file = os.path.join(local_path, file_name)
                    try:
                        if get_md5(p_local_file) != self.get_ftp_md5(file_name):
                            if get_local_last_modify(p_local_file) > self.get_ftp_last_modify(file_name, True):
                                self.upload_file(p_local_file, file_name)
                                log = Log(file_name, 1, get_now_time(), self.ftp.pwd() + '/' + file_name, 0)
                                self.print_log(log)
                            else:
                                self.download_file(p_local_file, file_name)
                                log = Log(file_name, 0, get_now_time(), p_local_file, 0)
                                self.print_log(log)
                    except Exception:
                        if get_local_last_modify(local_path) < self.get_ftp_last_modify(remote_path,
                                                                                        False):  # 下载文件
                            self.download_file(p_local_file, file_name)
                            log = Log(file_name, 0, get_now_time(), p_local_file, 1)
                            self.print_log(log)
                        else:  # 删除ftp文件
                            self.ftp.delete(file_name)
                            log = Log(file_name, 1, get_now_time(), self.ftp.pwd() + '/' + file_name, -1)
                            self.print_log(log)
                else:
                    p_local_path = os.path.join(local_path, file_name)
                    if not os.path.exists(p_local_path):
                        os.mkdir(p_local_path)
                        log = Log(file_name, 0, get_now_time(), p_local_path, 1)
                        self.print_log(log)
                    p_remote_path = self.ftp.pwd() + '/' + file_name  # 拼接FTP第一层子目录，递归时进入下一层
                    self.download_file_tree(p_local_path, p_remote_path)  # 递归
        except Exception as e:
            print(f'下载文件出错{e}')
        self.ftp.cwd("..")  # 对于递归 ftp 每次传输完成后需要切换目录到上一级

    # 关闭ftp
    def exit(self):
        self.stop()
        self.ftp.close()
        print('关闭ftp')

    def print_log(self, log):
        print(log.filename, log.flag, log.time, log.path, log.method)
        conn = sqlite3.connect('ignore.db')
        cursor = conn.cursor()
        cursor.execute('create table if not exists log(filename varchar(255), flag int, time varchar(255), '
                       'path varchar(255), method int)')
        cursor.execute('insert into log values (?,?,?,?,?)',
                       [log.filename, log.flag, log.time, log.path, log.method])
        conn.commit()
        cursor.close()
        conn.close()

    def get_log(self):
        conn = sqlite3.connect('ignore.db')
        cursor = conn.cursor()
        cursor.execute('create table if not exists log(filename varchar(255), flag int, time varchar(255), '
                       'path varchar(255), method int)')
        cursor.execute('select * from log')
        datas = cursor.fetchall()
        logs = []
        for i in datas:
            logs.append(i)
        conn.commit()
        cursor.close()
        conn.close()
        return logs


# 产生一个FtpConnect对象
myftp = FtpConnect(host='162.14.109.33')
